import time, datetime

from flask import abort
from sqlalchemy import not_

from info import constants, db
from info.modules.utils.file_storage import upload
from info.modules.utils.response_code import RET
from . import admin_blu
from flask import render_template, g, url_for, redirect, request, session, current_app, jsonify
from info.modules.utils.common import user_login_data
from info.models import User, News, Category


# 主页
@admin_blu.route("/")
@user_login_data
def admin_index():
    user = g.user
    # is_admin = user.is_admin if user else None
    # if not is_admin:
    #     return redirect(url_for("admin.admin_login"))

    context = {
        "user": user.to_dict()
    }
    return render_template("admin/index.html", context=context)


# 这个页面整个都是登录页面
@admin_blu.route("/login", methods=["GET", "POST"])
def admin_login():
    """登录页面"""

    # 1 GET请求
    if request.method == "GET":
        # 通过session获取状态信息
        user_id = session.get("user_id", None)
        is_admin = session.get("is_admin", False)
        if is_admin and user_id:
            return redirect(url_for("admin.admin_index"))
        else:
            return render_template("admin/login.html")

    # 2 POST 请求
    if request.method == "POST":

        # 2.1 获取参数
        user_name = request.form.get("username")
        password = request.form.get("password")

        # 2.2 校验参数
        if not all([user_name, password]):
            return render_template("admin/login.html", errmsg="缺少参数")

        try:
            user = User.query.filter(User.nick_name == user_name).first()
        except Exception as e:
            current_app.logger.error(e)
            return render_template("admin/login.html", errmsg="查询管理员用户失败")

        if not user:
            return render_template("admin/login.html", errmsg="用户名或密码错误")

        if not user.is_admin:
            return render_template("admin/login.html", errmsg="用户名或密码错误")

        if not user.check_password(password):
            return render_template("admin/login.html", errmsg="用户名或密码错误")

        # 2.3 设置状态保持信息
        session["user_id"] = user.id
        session["is_admin"] = user.is_admin
        session["nick_name"] = user.nick_name
        session["mobile"] = user.mobile

        # 2.4 响应结果
        return redirect(url_for("admin.admin_index"))


# 用户量统计
@admin_blu.route("/user_count")
def user_count():
    """用户统计"""

    # 获取当前时间now <class 'time.struct_time'>
    # time.struct_time(tm_year=2018, tm_mon=6, tm_mday=4, tm_hour=20, tm_min=2, tm_sec=21,
    #  tm_wday=0, tm_yday=155, tm_isdst=0)
    now_struct = time.localtime()

    # 用户总数
    total_count = 0
    try:
        total_count = User.query.filter(User.is_admin == False).count()
    except Exception as e:
        current_app.logger(e)

    # 用户当月增量
    month_count = 0
    month_begin = "%d-%02d-01" % (now_struct.tm_year, now_struct.tm_mon)
    month_begin_data = datetime.datetime.strptime(month_begin, "%Y-%m-%d")
    try:
        month_count = User.query.filter(User.is_admin == False, User.create_time >= month_begin_data).count()
    except Exception as e:
        current_app.logger.error(e)

    # 用户当日增量
    day_count = 0
    day_begin = "%d-%02d-%02d" % (now_struct.tm_year, now_struct.tm_mon, now_struct.tm_mday)
    day_begin_data = datetime.datetime.strptime(day_begin, "%Y-%m-%d")
    try:
        day_count = User.query.filter(User.is_admin==False, User.create_time>=day_begin_data).count()
    except Exception as e:
        current_app.logger.error(e)

    # 用户登录活跃数 X轴为时间, 单位天   Y轴为登录的用户登录量(最后登录时间在这一天的就算)
    today_str = "%d-%02d-%02d" % (now_struct.tm_year, now_struct.tm_mon, now_struct.tm_mday)
    today_datetime = datetime.datetime.strptime(today_str, "%Y-%m-%d")
    x_data_day = []
    y_data_count = []

    for i in range(15):
        begin_day_datetime = today_datetime - datetime.timedelta(days=i)
        end_day_datetime = today_datetime - datetime.timedelta(days=(i-1))
        x_data_day.append(begin_day_datetime.strftime("%Y-%m-%d"))
        try:
            count = User.query.filter(User.is_admin==False, User.last_login>=begin_day_datetime, User.last_login<end_day_datetime).count()
        except Exception as e:
            current_app.logger.error(e)
            count = 0
        y_data_count.append(count)

    x_data_day.reverse()
    y_data_count.reverse()

    context = {
        "total_count": total_count,
        "month_count": month_count,
        "day_count": day_count,
        "x_data_day": x_data_day,
        "y_data_count": y_data_count
    }
    return render_template("admin/user_count.html", context=context)


# 获取用户列表
@admin_blu.route("/user_list")
def user_list():
    """获取用户列表"""

    # 1. 获取参数 当前页数 page, 每页显示条数pre_page
    page = request.args.get("p", 1)
    pre_page = request.args.get("pre_page", constants.ADMIN_USER_PAGE_MAX_COUNT)

    # 2. 校验参数
    try:
        page = int(page)
        pre_page = int(pre_page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1
        pre_page = constants.ADMIN_USER_PAGE_MAX_COUNT

    # 3. 查询用户列表
    try:
        paginate = User.query.filter(User.is_admin==False).order_by(User.last_login.desc()).paginate(page, pre_page, False)
    except Exception as e:
        current_app.logger.error(e)
        paginate = None

    # 4. 构造数据
    users = paginate.items if paginate else []
    users_dict_list = []

    for user in users:
        users_dict_list.append(user.to_admin_dict())

    context = {
        'current_page': paginate.page if paginate else 1,
        'total_page': paginate.pages if paginate else 1,
        'users_list': users_dict_list
    }

    # 5. 响应
    return render_template("admin/user_list.html", context=context)


# 展示待审核页面
@admin_blu.route("/news_review")
def news_review():
    """待审核页面"""

    # 1. 接收参数 当前页page, 每页显示数据条数pre_page
    page = request.args.get("p", 1)
    pre_page = request.args.get("pre_page", constants.ADMIN_NEWS_PAGE_MAX_COUNT)
    keywords = request.args.get("keywords", "")

    # 2. 校验参数
    try:
        page = int(page)
        pre_page = int(pre_page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1
        pre_page = 1

    # 3. 查询数据
    filters = [News.status!=0]
    if keywords:
        filters.append(News.title.contains(keywords))
    try:
        paginate = News.query.filter(*filters).order_by(News.create_time.desc()).paginate(page, pre_page, False)
    except Exception as e:
        current_app.logger.error(e)
        paginate = None

    # 4. 组装数据
    news_list = paginate.items if paginate else []
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_review_dict())

    # 5. 响应数据
    context = {
        "news_list": news_dict_list,
        "current_page": paginate.page if paginate else 1,
        "total_page": paginate.pages if paginate else 1
    }

    return render_template("admin/news_review.html", context=context)


# 新闻审核页面
@admin_blu.route("/news_review_detail", methods=["GET", "POST"])
def news_review_detail():
    """审核新闻"""
    if request.method=="GET":
        # 1. 获取参数 news_id
        news_id = request.args.get("news_id")

        # 2. 校验参数
        if not news_id:
            return render_template("admin/news_review_detail.html", errmsg="未查询到新闻")

        # 3. 查询新闻
        try:
            news = News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            return render_template("admin/news_review_detail.html", errmsg="未查询到新闻")

        # 4. 构造数据,响应
        context = {
            "news": news.to_dict()
        }
        return render_template("admin/news_review_detail.html", context=context)

    if request.method=="POST":
        # 1. 获取参数 news_id 新闻id  action ["accept", "reject"]
        news_id = request.json.get("news_id")
        action = request.json.get("action")

        # 2. 校验参数
        if not all([news_id, action]):
            return jsonify(errno=RET.PARAMERR, errmsg="缺少参数")

        if action not in ["accept", "reject"]:
            return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

        # 3. 查询新闻
        try:
            news = News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="数据查询错误")

        if not news:
            return jsonify(errno=RET.NODATA, errmsg="要操作的新闻不存在")

        # 4. 根据action处理数据
        if action == "accept":
            news.status = 0
        else:
            reason = request.json.get("reason")
            if not reason:
                return jsonify(errno=RET.PARAMERR, errmsg="缺少参数")
            news.reason = reason
            news.status = -1

        # 5. 提交数据
        try:
            db.session.commit()
        except Exception as e:
            current_app.logger.error(e)
            db.session.rollback()
            return jsonify(errno=RET.DBERR, errmsg="同步数据库失败")

        # 6. 响应
        return jsonify(errno=RET.OK, errmsg="操作成功")


# 新闻版式编辑,新闻列表
@admin_blu.route("/news_edit")
def news_edit():
    """新闻版式编辑首页"""

    # 1. 接收参数 page 当前页, pre_page 每页显示多少新闻, keywords 关键字
    page = request.args.get("p", 1)
    pre_page = request.args.get("pre_page", constants.ADMIN_NEWS_PAGE_MAX_COUNT)
    keywords = request.args.get("keywords", "")

    # 2. 校验参数
    try:
        page = int(page)
        pre_page = int(pre_page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1
        pre_page = constants.ADMIN_NEWS_PAGE_MAX_COUNT

    # 3. 查询新闻
    try:
        filters = []
        if keywords:
            filters.append(News.title.contains(keywords))
        filters.append(News.status == 0)

        paginate = News.query.filter(*filters).order_by(News.create_time.desc()).paginate(page, pre_page, False)
    except Exception as e:
        current_app.logger.error(e)
        paginate = None

    # 4. 返回数据
    news_list = paginate.items if paginate else None
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_dict())

    context = {
        "current_page": paginate.page if paginate else 1,
        "total_page": paginate.pages if paginate else constants.ADMIN_NEWS_PAGE_MAX_COUNT,
        "news_list": news_dict_list
    }
    return render_template("admin/news_edit.html", context=context)


# 新闻版式编辑,编辑页面展示,编辑功能
@admin_blu.route("/news_edit_detail/<int:news_id>", methods=["GET", "POST"])
def news_edit_detail(news_id):
    """新闻版式编辑"""
    if request.method == "GET":
        try:
            news = News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            news = None
            abort(404)

        try:
            categories = Category.query.filter(Category.id != 1).all()
        except Exception as e:
            current_app.logger.error(e)
            categories = []
            abort(404)
        context = {
            "news": news.to_dict() if news else None,
            "categories": categories
        }
        return render_template("admin/news_edit_detail.html", context=context)

    if request.method == "POST":
        # 1. 接收参数title category_id digest content [news_image]
        news_title = request.form.get("title")
        news_category_id = request.form.get("category_id")
        news_digest = request.form.get("digest")
        news_content = request.form.get("content")
        news_image = request.files.get("news_image")

        # 2. 校验参数
        try:
            news = News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="查询新闻失败")

        if not news:
            return jsonify(errno=RET.NODATA, errmsg="该新闻不存在")

        if not all([news_title, news_category_id, news_digest, news_content]):
            return jsonify(errno=RET.PARAMERR, errmsg="缺少参数")

        try:
            news_category_id = int(news_category_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

        if news_image:
            try:
                key = upload(news_image.read())
            except Exception as e:
                current_app.logger.error(e)
                return jsonify(errno=RET.THIRDERR, errmsg="上传新闻图片失败")
            # 在这个位置比较好, 产生bug几率小
            news.index_image_url = constants.QINIU_DOMIN_PREFIX + key

        # 3. 同步数据库
        news.title = news_title
        news.category_id = news_category_id
        news.digest = news_digest
        news.content = news_content
        # 新闻修改之后将状态改为待审核
        news.status = 1

        try:
            db.session.commit()
        except Exception as e:
            current_app.logger.error(e)
            db.session.rollback()
            return jsonify(errno=RET.DBERR, errmsg="操作失败")

        return jsonify(errno=RET.OK, errmsg="操作成功")


# 新闻分类的管理
@admin_blu.route("/news_type", methods=["GET", "POST"])
def news_type():
    """新闻分类的管理"""
    if request.method == "GET":
        categories = []
        try:
            categories = Category.query.filter(Category.id != 1).all()
        except Exception as e:
            current_app.logger.error(e)
            abort(404)

        context = {
            "categories": categories
        }
        return render_template("admin/news_type.html", context=context)

    if request.method == "POST":
        # 1. 接收参数 category_name  category_id

        # json.get()获取数据不存在
        category_name = request.json.get("name")
        category_id = request.json.get("id")
        if not category_name:
            return jsonify(errrno=RET.PARAMERR, errmsg="缺少参数")

        # 2. 根据有无参数category_id , 判断是修改分类还是新增分类
        # 3. 根据需求进行数据操作
        if category_id:
            # 修改新闻分类
            try:
                category = Category.query.get(category_id)
            except Exception as e:
                current_app.logger.error(e)
                return jsonify(errno=RET.DBERR, errmsg="数据查询失败")

            if not category:
                return jsonify(errno=RET.NODATA, errmsg="数据不存在")

            category.name = category_name
        else:
            # 新增新闻分类
            try:
                categories = Category.query.all()
            except Exception as e:
                current_app.logger.error(e)
                return jsonify(errno=RET.DBERR, errmsg="数据库查询错误")

            category_names = []
            for category in categories:
                category_names.append(category.name)

            if category_name in category_names:
                return jsonify(errno=RET.DATAEXIST, errmsg="分类已经存在")
            else:
                new_category = Category()
                new_category.name = category_name
                # 添加只能放在这了
                db.session.add(new_category)

        # 4. 同步数据库

        try:
            db.session.commit()
        except Exception as e:
            current_app.logger.error(e)
            db.session.rollback()
            jsonify(errno=RET.DBERR, errmsg="同步数据失败")

        # 5. 响应结果
        return jsonify(errno=RET.OK, errmsg="错做成功")
